/*
 * This code is a demo for Ian Upton's 2nd Life Application
 */
package application.controller;

import application.externalServices.AlchemyTermExtractor;
import application.externalServices.DiscoWordnetService;
import application.model.Blacklist;
import application.model.EntitySearchResults;
import application.service.BlacklistService;
import application.service.EntityAccomplishmentService;
import application.service.EntitySearchResultsService;
import application.tools.ConflationTool;
import application.validator.SearchFormValidator;
import java.util.ArrayList;
import java.util.Arrays;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author aa6345
 */
@Controller
@SessionAttributes
public class BasicAPIController {

    @Autowired
    private EntityAccomplishmentService entityAccomplishmentService;
    @Autowired
    private EntitySearchResultsService entitySearchResultsService;
    @Autowired
    private BlacklistService blacklistService;    

    @RequestMapping(value = "/basicapi", method = RequestMethod.GET, params = {"kwrd", "appkey"})
    public ModelAndView showKwrdSearch(@RequestParam("kwrd") String kword, @RequestParam("appkey") String appkey) {
        //try {
        //check if the appkey is valid //could improve this by getting list of approved key from a db table
        if (appkey.equals("projectinspires2012")) {
            

            String results = this.search(kword);
            return new ModelAndView("basicapi").addObject("results", results);

            /*
            if (outputString3.length() < 1 && outputString.length() < 1) {
                return new ModelAndView("basicapi").addObject("results", "Keyword search returned 0 matches! \"" + kword + "\"");
            } else {
                //remove last |
                //outputString4 = outputString3.substring(0, outputString3.length() - 1);

                return new ModelAndView("basicapi").addObject("results", outputString + outputString3);
            }
             *
             */
            //} catch (Exception e) {
            //    return new ModelAndView("secondlifeapp").addObject("results", "Keyword search failed: \"" + kword +"\"");
            //}
        } else {
            return new ModelAndView("basicapi").addObject("results", "Error 2: wrong parameters");
        }
    }

    @RequestMapping(value = "/basicapi", method = RequestMethod.GET)
    public ModelAndView defaultPage() {
        return new ModelAndView("basicapi").addObject("results", "Error 1: wrong parameters");
    }

    @RequestMapping(value = "/basicapi", method = RequestMethod.GET, params = {"kwrd", "appkey", "service"})
    public ModelAndView showKwrdSearch(@RequestParam("kwrd") String kword, @RequestParam("appkey") String appkey, @RequestParam("service") String service) {
        //try {
        String outputString = "";
        //check if the appkey is valid //could improve this by getting list of approved key from a db table
        if (appkey.equals("projectinspires2012")) {

            if (service.equals("synonyms")) {

                //remove last
/*
                //do DW search for conflation
                DiscoWordnetService discowordnet = new DiscoWordnetService();
                discowordnet.setAccessKey("additional7185information1519regarding");

                //DO DISCO Wordnet search
                //check D/W results and only select the ones that contain search term
                //(ie. st=waste, dw=wastes then select).
                discowordnet.setSearchKeyword(kword.trim());
                discowordnet.createURLWithText();
                discowordnet.startDiscoWordnetService();
                discowordnet.extractXMLKeywords();

                //remove duplicates from the discoWordnet result
                ArrayList discowordnetExtractedKeywords = new ArrayList();
                HashSet hs = new HashSet();
                hs.addAll(discowordnet.getExtractedKeywords());
                discowordnetExtractedKeywords.clear();
                discowordnetExtractedKeywords.addAll(hs);

                //System.out.println(discowordnetExtractedKeywords.toString());

                for (int kwdnum3 = 0; kwdnum3 < discowordnetExtractedKeywords.size(); kwdnum3++) {
                    outputString += discowordnetExtractedKeywords.get(kwdnum3).toString() + "|,|";
                }
   */
                String results = this.search(kword);
                AlchemyTermExtractor urlcn = new AlchemyTermExtractor();
                //alchemy service doesn't like too long strings.  Create repeated calls of length 4000 chars
                System.out.println("results length is: "+results.length());
                if(results.length()>4000) {
                    for (int xy=0; xy<results.length(); xy=xy+4000) {
                        if(results.length() > xy+4000) {
                            urlcn.setFullText(results.substring(xy, xy+4000));
                        } else {
                            urlcn.setFullText(results.substring(xy, results.length()));
                        }
                        urlcn.createURLWithText();
                        urlcn.startTermExtract();
                        urlcn.extractXMLKeywords();
                        System.out.println(urlcn.getExtractedKeywords());
                        outputString += urlcn.getExtractedKeywords();

                    }
                }

                //the result will have duplicates.  removet them.
                HashSet hs = new HashSet();
                outputString = outputString.replace("[", "").replace("]", ",");
                String[] tmpResultsArray = outputString.split(",");
                hs.addAll(Arrays.asList(tmpResultsArray));
                outputString = hs.toString();
                outputString = outputString.replace(",", "|,|");
            }
            if (outputString.length() < 1) {
                return new ModelAndView("basicapi").addObject("results", "Keyword search returned 0 matches! \"" + kword + "\"");
            } else {
                //remove last |
                //outputString4 = outputString.substring(0, outputString.length() - 1);

                return new ModelAndView("basicapi").addObject("results", outputString);
            }
            //} catch (Exception e) {
            //    return new ModelAndView("secondlifeapp").addObject("results", "Keyword search failed: \"" + kword +"\"");
            //}
        } else {
            return new ModelAndView("basicapi").addObject("results", "Error 2: wrong parameters");
        }
    }

    private String search(String kword) {
        List searchResults = null;  //list of query results
            SearchFormValidator sfv = new SearchFormValidator(); //input validation tool
            HashMap<String, String> validatedFormValues = new HashMap<String, String>(); //contains validated input values
            List<Blacklist> blacklistTerms = blacklistService.listAllBlacklistTerms();

            //validatedFormValues.put("searchTerm1", sfv.validateSearchTerm(URLDecoder.decode(kword, "UTF-8")));
            validatedFormValues.put("searchTerm1", sfv.validateSearchTerm(kword));
            validatedFormValues.put("searchOperator", "none");
            validatedFormValues.put("searchTerm1Synonyms", "");

            //get all matching entityAccomplishments (1 or more entities)
            searchResults = entitySearchResultsService.listSelectedEntitySearchResults(validatedFormValues);

            //get unique entity names and add them to outputString with | as delimiter
            String outputString = "";
            for (int i = 0; i < searchResults.size(); i++) {
                //if(!outputString.contains(searchResults.get(i).toString())) {
                EntitySearchResults esr = (EntitySearchResults) searchResults.get(i);
                outputString += esr.getEntityFname() + " " + esr.getEntitySname() + "|,|" + esr.getAccompTitle() + "|#|";
                //}
            }

            //remove last

            //do DW search for conflation
            DiscoWordnetService discowordnet = new DiscoWordnetService();
            discowordnet.setAccessKey("additional7185information1519regarding");

            ConflationTool ct = new ConflationTool();


            //DO DISCO Wordnet search
            //check D/W results and only select the ones that contain search term
            //(ie. st=waste, dw=wastes then select).
            discowordnet.setSearchKeyword(kword.trim());
            discowordnet.createURLWithText();
            discowordnet.startDiscoWordnetService();
            discowordnet.extractXMLKeywords();
            String outputString3 = "";
            //String outputString4 = "";

            //remove duplicates from the discoWordnet result
            ArrayList discowordnetExtractedKeywords = new ArrayList();
            HashSet hs = new HashSet();
            hs.addAll(discowordnet.getExtractedKeywords());
            discowordnetExtractedKeywords.clear();
            discowordnetExtractedKeywords.addAll(hs);

            //System.out.println(discowordnetExtractedKeywords.toString());
            for (int kwdnum3 = 0; kwdnum3 < discowordnetExtractedKeywords.size(); kwdnum3++) {

                String dwKwordAsString = discowordnetExtractedKeywords.get(kwdnum3).toString();

                if (!dwKwordAsString.trim().equals(kword.trim())) {
                    //blacklist check
                    Boolean inBlacklist = false;  // used for blacklist check
                    //blacklist check
                    for (int blkX = 0; blkX < blacklistTerms.size(); blkX++) {
                        if (blacklistTerms.get(blkX).getBlacklistTerm().trim().toLowerCase().equals(dwKwordAsString.trim().toLowerCase())) {
                            inBlacklist = true;
                        }
                    }

                    if (inBlacklist == false) {

                        //System.out.println("source - keyword is:" + kword);
                        //System.out.println("DW - target - keyword is:" + dwKwordAsString);
                        //Conflation. check if the source word and the target word (DW term) match 66% +
                        if (ct.howManyMatchingChars(kword.trim(), dwKwordAsString)) {
                            //get all matching entityAccomplishments (1 or more entities)
                            searchResults.clear();
                            validatedFormValues.put("searchTerm1", dwKwordAsString);
                            searchResults = entitySearchResultsService.listSelectedEntitySearchResults(validatedFormValues);

                            //get unique entity names and add them to outputString with | as delimiter

                            for (int i = 0; i < searchResults.size(); i++) {
                                EntitySearchResults esr = (EntitySearchResults) searchResults.get(i);
                                outputString3 += esr.getEntityFname() + " " + esr.getEntitySname() + "|,|" + esr.getAccompTitle() + "|#|";

                            }
                        }
                    }
                }
            }

            String result = "";
            if (outputString3.length() < 1 && outputString.length() < 1) {
                result = "Keyword search returned 0 matches! \"" + kword + "\"";

            } else {
                //remove last |
                //outputString4 = outputString3.substring(0, outputString3.length() - 1);

                result = outputString + outputString3;
            }

            return result;
    }
}
